/** 
Copyright (c) 2010, Sheikh Abdul Wahid Ahmed
Details @ http://extremecodeworld.codeplex.com/license
**/

using System;
using System.Collections;
using System.Data;
using System.Xml;
using EXtremecode.Utils;

namespace EXtremecode.EntityDefinition
{
	/// <summary>
	/// Summary description for DBEntity.
	/// </summary>
	public class DBEntity:Entity
	{
		public class FieldType
		{
			public const string NATIVE="native";
			public const string REFERENCE="reference";
		}
		public class DBEntityType
		{
			public const string TABLE="table";
			public const string VIEW="view";
		}
		private const string TYPE="db";
		private static string VIEW_PREFIX=Configurations.Provider.ViewPrefix;
		private string m_strDBEntityType;
		private string m_strView="";
		public DBEntity(DataTable dt):this(dt,DBEntity.DBEntityType.TABLE)
		{}
		public DBEntity(DataTable dt,string strDBEntityType):base(dt.TableName,TYPE)
		{
			if(dt.ExtendedProperties.Contains("AccessorName"))
			{
				m_accessorName=dt.ExtendedProperties["AccessorName"].ToString();
			}
			m_strDBEntityType=strDBEntityType; 
			PopulateEntityFields(dt);
		}
		private void PopulateEntityFields(DataTable dt)
		{
			foreach(DataColumn dc in dt.Columns)
			{
				m_entityFieldCollection.Add(dc.ColumnName,new DBEntityField(dc,(m_strDBEntityType==DBEntityType.TABLE)? FieldType.NATIVE: FieldType.REFERENCE,this)); 
			}
		}
		
		public static  void CreateEntities(DataSet ds)
		{
			foreach(DataTable dt in ds.Tables)
			{
				try
				{
					if(IsTableSelectedForEntity(dt))
					{
						string type=dt.ExtendedProperties["Type"].ToString();
						if(type=="View")
						{
							string accessorName=dt.ExtendedProperties["AccessorName"].ToString();
							string tableName= StringProcessor.LeftTrim(
								StringProcessor.LeftTrim(dt.TableName,string.Format("{0}-",accessorName)),
								VIEW_PREFIX);
							string viewName=StringProcessor.LeftTrim(dt.TableName,string.Format("{0}-",accessorName));
								
							//if table is not duplicate then use table name as extracted above
							//other wise attach accessor name with string as a prefix.

							DBEntity entityWithAccessorName=
								s_entityCollectionCreated[string.Format("{0}-{1}",accessorName,tableName)] as DBEntity; 
							DBEntity entity =
								s_entityCollectionCreated[tableName] as DBEntity;
							
							if(entityWithAccessorName != null)
							{
								entity=entityWithAccessorName;
							}


			
							if(entity != null && entity.AccessorName==accessorName )
							{
								entity.View=viewName;
								foreach(DataColumn dc in dt.Columns)
								{
									entity.AddField(new DBEntityField(dc,DBEntity.FieldType.REFERENCE,entity)); 
								}

							}
							else
							{
								s_entityCollectionCreated.Add(dt.TableName,new DBEntity(dt,DBEntity.DBEntityType.VIEW));
							}
						}
						else
						{
							s_entityCollectionCreated.Add(dt.TableName,new DBEntity(dt));
						}
					}
				}
				catch(Exception ex)
				{
					throw Logging.Logger.Write(ex,string.Format("Entity Name = {0}",dt.TableName));
				}
			}
			MakeRelations(ds);
			
		}
		public string View
		{
			get
			{
				return m_strView;
			}
			set
			{
				m_strView=value;
			}
		}
		public string AccessorName
		{
			get
			{
				return m_accessorName;
			}
			set
			{
				m_accessorName=value;
			}
		}
		public override XmlElement BuildXml(XmlDocument ownerDocument)
		{
			XmlElement element= base.BuildXml (ownerDocument);
			XmlAttribute atb;

			
			
			//----tableName---
			atb= ownerDocument.CreateAttribute("table");
			atb.InnerText=Name; 
			if(Name.IndexOf('-') > 0)
			{
				atb.InnerText=Name.Substring(Name.IndexOf('-')+1);
			}
			element.Attributes.Append(atb);

			//---View-----
			atb= ownerDocument.CreateAttribute("view");
			atb.InnerText=(m_strView != "")? m_strView: element.Attributes["table"].Value;
			element.Attributes.Append(atb);
			return element;
		}

		private static void MakeRelations(DataSet ds)
		{
			MakeChildRelations(ds);
			MakeParentRelations(ds);
		}
		private static void MakeChildRelations(DataSet ds)
		{
			foreach(DataTable dt in ds.Tables)
			{
				if(IsTableSelectedForEntity(dt))
				{
					Entity entityNative=s_entityCollectionCreated[dt.TableName];
					foreach(DataRelation rel in dt.ChildRelations)
					{
						if(IsTableSelectedForEntity(rel.ChildTable))
						{
							for(int i=0; i<rel.ChildColumns.Length; i++)
							{
								DataColumn dcReference=rel.ChildColumns[i];
								DataColumn dcNative=rel.ParentColumns[i];
								Entity entityReference=s_entityCollectionCreated[dcReference.Table.TableName];
								entityNative.AddChild(entityReference[dcReference.ColumnName],dcNative.ColumnName);
							}
						}
					
					}
				}
			}
		}
		private static void MakeParentRelations(DataSet ds)
		{
			foreach(DataTable dt in ds.Tables)
			{
				if(IsTableSelectedForEntity(dt))
				{
					Entity entityNative=s_entityCollectionCreated[dt.TableName];
					foreach(DataRelation rel in dt.ParentRelations)
					{
						if(IsTableSelectedForEntity(rel.ParentTable))
						for(int i=0; i<rel.ParentColumns.Length; i++)
						{
							DataColumn dcReference=rel.ParentColumns[i];
							DataColumn dcNative=rel.ChildColumns[i];
							Entity entityReference=s_entityCollectionCreated[dcReference.Table.TableName];
							entityNative.AddParent(entityReference[dcReference.ColumnName],dcNative.ColumnName);
						}
					
					}
				}
			}
		}
		
		

	}

}
